package utils;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 日期转换工具类
 */
public class DateConversionUtils {
    private static final Logger log = LoggerFactory.getLogger(DateConversionUtils.class);

    public static String DateToString(Date date){
        return new SimpleDateFormat("yyyy年MM月dd日").format(date);
    }

    public static String DateToStringNew(Date date){
        try {
            return new SimpleDateFormat("yyyy年M月d日").format(date);
        }catch (Exception e){
            return "";
        }
    }

    public static String DateToYMDHMSChineseString(Date date){
        return new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒").format(date);
    }

    public static String DateToMDHMString(Date date){
        return new SimpleDateFormat("M月d日HH点mm分").format(date);
    }





    public static Date StringToDate(String time) {
        // 定义一个SimpleDateFormat对象，其格式与输入的字符串相匹配
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        try {
            // 使用SimpleDateFormat解析字符串为Date对象
             date = sdf.parse(time);
        } catch (ParseException e) {
            // 如果字符串不能按照指定格式解析，则会抛出ParseException异常
            e.printStackTrace();
        }
        return date;
    }
    public static String DateToStringYYYYMMDD(Date date){
        try {
            return new SimpleDateFormat("yyyy-MM-dd").format(date);
        }catch (Exception e){
            return "";
        }
    }

    public static String DateToYYYYMMDD(Date date){
        return new SimpleDateFormat("yyyyMMdd").format(date);
    }

    public static String DateToDays(Date date){
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    }

    public static String DateToYMDMM(Date date){
        return new SimpleDateFormat("yyyy-MM-dd HH:mm").format(date);
    }

    public static String DateToYear(Date date){
        return new SimpleDateFormat("yyyy").format(date);
    }

    public static String DateToIntegerMonth(Date date){
        return new SimpleDateFormat("MM").format(date);
    }

    public static String DateToIntegerMonth2(Date date){
        return new SimpleDateFormat("M").format(date);
    }

    public static String DateToMonth(Date date){
        return new SimpleDateFormat("yyyy-MM").format(date);
    }

    public static String DateToMonthTwo(Date date){
        return new SimpleDateFormat("yyyyMM").format(date);
    }

    public static Date convertStringToDateYear(String date){
        return DateUtil.parse(date, "yyyy");
    }

    public static Date convertStringToDateYearMonth(String date){
        return DateUtil.parse(date, "yyyy-MM");
    }

    public static Date convertStringToDateYmd(String date){
        return DateUtil.parse(date, "yyyy-MM-dd");
    }

    public static Date convertStringToDateYmdHm(String date){
        return DateUtil.parse(date, "yyyy-MM-dd HH:mm");
    }

    public static Date convertStringToDateYmdHms(String date){
        return DateUtil.parse(date, "yyyy-MM-dd HH:mm:ss");
    }

    /** 验证日期字符串是否合法
     * @param dateStr
     * @return true: 合法
     */
    public static boolean isValidDateStringYmd(String dateStr) {
        if (StringUtils.isBlank(dateStr)){
            return false;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 定义日期格式
        sdf.setLenient(false); // 不允许不严格的解析
        try {
            sdf.parse(dateStr); // 尝试解析日期
            return true; // 如果没有抛出异常，则返回true
        } catch (ParseException e) {
            return false; // 如果抛出ParseException，则返回false
        }
    }

    public static Date LocalDateToDate(Date date){
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDate localDate = localDateTime.toLocalDate();
        date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
        return date;
    }

    /** 获取两个日期之间的全部日期列表 */
    public static List<String> getTwoDateMidDateList(Date startTime, Date endTime){

        if (startTime == null){
            return new ArrayList<String>(1);
        }

        long midDay = 0;
        if (endTime != null && !startTime.equals(endTime)) {
            if (startTime.before(endTime)) {
                midDay = DateUtil.between(startTime, endTime, DateUnit.DAY); // 相差天数
            }
        }


        List<String> dateList = new ArrayList<>();
        dateList.add(DateToStringYYYYMMDD(startTime));
        Date nowDate = startTime;
        for (int i = 0; i < midDay; i++){
            nowDate = DateUtil.offsetDay(nowDate, 1);
            dateList.add(DateToStringYYYYMMDD(nowDate));
        }
        return dateList;
    }

    /** 去除年月日 中 包含的0 */
    public static String DateToYMDString(String nowDate){
        StringBuffer stringBuffer = new StringBuffer(nowDate);
        if (stringBuffer.substring(8, 9).equals("0")) {
            stringBuffer.replace(8, 9, "");
        }
        if (stringBuffer.substring(5, 6).equals("0")) {
            stringBuffer.replace(5, 6, "");
        }
        return stringBuffer.toString();
    }

    /** 去除月份中 包含的0 */
    public static String DateToMonthString(String month){
        StringBuffer stringBuffer = new StringBuffer(month);
        if (stringBuffer.substring(0, 1).equals("0")) {
            stringBuffer.replace(0, 1, "");
        }
        return stringBuffer.toString();
    }

    /**
     * 身份证号-获取出生日期
     * @param idCard 身份证号码
     * @return 返回日期格式
     */
    public static Date getBirthDayFromIdCard(String idCard) throws ParseException {
        Date birth = null;
        if (idCard.length() == 18) {
            String year = idCard.substring(6).substring(0, 4);// 得到年份
            String month = idCard.substring(10).substring(0, 2);// 得到月份
            String day = idCard.substring(12).substring(0, 2);// 得到日
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            birth = format.parse(year + "-" + month + "-" + day);
        } else if (idCard.length() == 15) {
            String year = "19" + idCard.substring(6, 8);// 年份
            String month = idCard.substring(8, 10);// 月份
            String day = idCard.substring(10, 12);// 得到日
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            birth = format.parse(year + "-" + month  + "-" + day);
        }
        return birth;
    }

    /**
     * 身份证号-获取出生年月
     * @param idCard 身份证号码
     * @return 返回日期格式
     */
    public static Date getBirthYmFromIdCard(String idCard) throws ParseException {
        Date birth = null;
        if (idCard.length() == 18) {
            String year = idCard.substring(6).substring(0, 4);// 得到年份
            String month = idCard.substring(10).substring(0, 2);// 得到月份
//            String day = idCard.substring(12).substring(0, 2);// 得到日
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
            birth = format.parse(year + "-" + month);
        } else if (idCard.length() == 15) {
            String year = "19" + idCard.substring(6, 8);// 年份
            String month = idCard.substring(8, 10);// 月份
//            String day = idCard.substring(10, 12);// 得到日
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
            birth = format.parse(year + "-" + month);
        }
        return birth;
    }

    /**
     * 身份证号-获取出生年
     */
    public static String getBirghYearFromIdCary(String idCard){
        if (StringUtils.isBlank(idCard)){
            return "";
        }

        if (idCard.length() > 9){
            return idCard.substring(6).substring(0, 4);
        }

        return "";
    }

    /**
     * 身份证号-获取性别
     * @param idCard 身份证号码
     * @return int 0=未知的性别,9=未说明的性别,2=女性,1=男性
     */
    public static int getSexFromIdCard(String idCard) {
        int sex = 9;
        // 身份证号码为空
        if (idCard == "" || idCard.length() <= 0){
            return sex = 0;
        }
        if (idCard.length() == 18) {
            if (Integer.parseInt(idCard.substring(16).substring(0, 1)) % 2 == 0) {// 判断性别
                sex = 2; // 女
            } else {
                sex = 1; // 男
            }
        } else if (idCard.length() == 15) {
            String usex = idCard.substring(14, 15);// 用户的性别
            if (Integer.parseInt(usex) % 2 == 0) {
                sex = 2; // 女
            } else {
                sex = 1; // 男
            }
        }
        return sex;
    }

    public static Date parseStringDate(String dateStr) {
        if (dateStr == null
                || !dateStr
                .matches("\\d{4}-\\d{1,2}-\\d{1,2}(\\s+\\d{1,2}:\\d{1,2}:\\d{1,2})?(\\.\\d{1,3})?"))
            return null;
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(0);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        String[] yd = dateStr.split(" ");
        String[] pts = yd[0].split("-");
        cal.set(Calendar.YEAR, Integer.parseInt(pts[0]));
        cal.set(Calendar.MONTH, Integer.parseInt(pts[1]) - 1);
        cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(pts[2]));
        if (yd.length == 2) {
            pts = yd[1].split("[:\\.]");
            cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(pts[0]));
            cal.set(Calendar.MINUTE, Integer.parseInt(pts[1]));
            cal.set(Calendar.SECOND, Integer.parseInt(pts[2]));
        }
        return cal.getTime();
    }

    /**
     * 加减对应时间后的日期
     * @param date  需要加减时间的日期
     * @param amount    加减的时间(毫秒)
     * @return  加减对应时间后的日期
     * @return
     */
    public static Date subtractTime(Date date,int amount){
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String strTime = sdf.format(date.getTime() - amount);
            Date time = sdf.parse(strTime);
            return time;
        }catch (Exception e){
            log.error("加减日期错误-{}",e.getMessage());
        }
        return null;
    }

    /**
     * date2比date1多的天数
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDays(Date date1,Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1= cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if(year1 != year2) {//不同一年
            int timeDistance = 0 ;
            for(int i = year1 ; i < year2 ; i ++)
            {
                if(i%4==0 && i%100!=0 || i%400==0)    //闰年
                {
                    timeDistance += 366;
                }
                else    //不是闰年
                {
                    timeDistance += 365;
                }
            }

            return timeDistance + (day2-day1)+1;
        } else {// 同年
            return (day2-day1)+1;
        }
    }

    /**
     * 获取两个日期之间的间隔多少分钟
     * @param startTime
     * @param endTime
     * @return
     * @throws Exception
     */
    public static long dateDiffWithDays(String startTime, String endTime) throws Exception {
        //按照传入的格式生成一个simpledateformate对象

        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        long nd = 1000*24*60*60;//一天的毫秒数

        long nh = 1000*60*60;//一小时的毫秒数

        long nm = 1000*60;//一分钟的毫秒数

        long ns = 1000;//一秒钟的毫秒数

        long diff;

        //获得两个时间的毫秒时间差异

        diff = sd.parse(endTime).getTime() - sd.parse(startTime).getTime();

        long day = diff/nd;//计算差多少天

        long hour = diff%nd/nh;//计算差多少小时

        long min = diff%nd%nh/nm;//计算差多少分钟

        long sec = diff%nd%nh%nm/ns;//计算差多少秒//输出结果

        log.info("时间相差："+day+"天"+hour+"小时"+min+"分钟"+sec+"秒。");
        if (sec > 0){
            min = min + 1;
        }
        if (day>0){
            min = min + (int)day*24*60;;
        }
        if (hour>0){
            min = min + (int)hour*60;
        }

        return min;
    }


    public static long dateDiffWithDay(String startTime, String endTime) throws Exception {
        //按照传入的格式生成一个simpledateformate对象


        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");

        long nd = 1000*24*60*60;//一天的毫秒数

        long nh = 1000*60*60;//一小时的毫秒数

        long nm = 1000*60;//一分钟的毫秒数

        long ns = 1000;//一秒钟的毫秒数

        long diff;

        //获得两个时间的毫秒时间差异

        diff = sd.parse(endTime).getTime() - sd.parse(startTime).getTime();

        long day = diff/nd +1;//计算差多少天
        log.info("时间相差："+day+"天");
        return day;
    }

    /**
     * 获取日期里面的年份
     */
    public static int getYearByDate(Date date){
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        int nowYear = calender.get(Calendar.YEAR);
        int nowMonth = calender.get(Calendar.MONTH)+1; // 当前月份
//        log.info("日期：{}，当前年份：{},当前月份: {}",date,nowYear,nowMonth);

        return nowYear;
    }

    /**
     * 获取日期里面的月份
     * @param date
     * @return
     */
    public static int getMonthByDate(Date date){
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        int nowYear = calender.get(Calendar.YEAR);
        int nowMonth = calender.get(Calendar.MONTH)+1; // 当前月份
//        log.info("日期：{}，当前年份：{},当前月份: {}",date,nowYear,nowMonth);

        return nowMonth;
    }

    /**
     * 对一个时间基于小时进行加减操作
     */
    public static Date changeDateBaseHour(Date date, int changeHours){
        if (changeHours == 0){
            return date;
        }
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);

        // 基于小时进行加减操作
        instance.add(Calendar.HOUR, changeHours);

        return instance.getTime();
    }

    /**
     * 判断给定的时分字符串是否在开始时间和结束时间之间。
     *
     * @param timeStr      要检查的时间字符串，格式为"HH:mm"。
     * @param startTimeStr 开始时间字符串，格式为"HH:mm"。
     * @param endTimeStr   结束时间字符串，格式为"HH:mm"。
     * @return 如果时间在指定范围内则返回true，否则返回false。
     */
    public static boolean isTimeBetween(String timeStr, String startTimeStr, String endTimeStr) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");

        try {
            LocalTime time = LocalTime.parse(timeStr, formatter);
            LocalTime startTime = LocalTime.parse(startTimeStr, formatter);
            LocalTime endTime = LocalTime.parse(endTimeStr, formatter);

            return !time.isBefore(startTime) && !time.isAfter(endTime);
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("Invalid time format. Please use 'HH:mm'.", e);
        }
    }






}
